﻿#include"snake.h"
void setpos(int x, int y)
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD coord;
	coord.X = x;
	coord.Y = y;
	SetConsoleCursorPosition(handle, coord);
}
void welcome()
{
	system("mode con cols=100 lines=30");
	system("title 贪吃蛇");
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_CURSOR_INFO cursor;
	GetConsoleCursorInfo(handle, &cursor);
	cursor.bVisible = false;
	SetConsoleCursorInfo(handle, &cursor);
	setpos(40, 10);
	printf("欢迎来到贪吃蛇游戏！");
	setpos(40, 20);
	system("pause");
	system("cls");
	setpos(38, 10);
	printf("游戏规则如下:\n");
	setpos(38, 11);
	printf("1.用← → ↑ ↓进行操作");
	setpos(38, 12);
	printf("2.用f1进行加速，用进行f2减速");
	setpos(38, 13);
	printf("3.空格键暂停游戏");
	setpos(38, 14);
	printf("4.esc退出游戏");
	setpos(40, 20);
	system("pause");
	system("cls");
}
void creatmap()
{
	setpos(0, 0);
	for (int i = 0; i < 58; i+=2)
	{
		wprintf(L"%c",Wall);
	}
	setpos(0, 25);
	for (int i = 0; i < 58; i+=2)
	{
		wprintf(L"%c",Wall);
	}
	for (int i = 1; i < 25; i++)
	{
		setpos(0, i);
		wprintf(L"%c",Wall);
	}
	for (int i = 1; i < 25; i++)
	{
		setpos(56, i);
		wprintf(L"%c",Wall);
	}
}
void initsnake(pSnake snake)
{
	snake->_snake = NULL;
	snake->_food = NULL;
	snake->_score = 0;
	snake->dir = left;
	snake->sta = ok;
	snake->_weight = 10;
	snake->_sleeptime = 200;
}
void creatsnake(pSnake snake)
{
	pSnakeNode p = (pSnakeNode)malloc(sizeof(SnakeNode));
	assert(p);
	p->next = NULL;
	p->x = 24;
	p->y = 5;
	snake->_snake = p;
	setpos(p->x, p->y);
	wprintf(L"%c", Body);
	for(int i=1;i<5;i++)
	{
		pSnakeNode j = (pSnakeNode)malloc(sizeof(SnakeNode));
		assert(j);
		j->x = 24 + i * 2;
		j->y = 5;
		j->next = NULL;
		setpos(j->x, j->y);
		wprintf(L"%c", Body);
		p->next = j;
		p = p->next;
	}
}
void creatfood(pSnake snake)
{
	int x, y;
	pFood food = (pFood)malloc(sizeof(Food));
	assert(food);
	again:
		do {
			x = rand() % 53 + 2;
			y = rand() % 24 + 1;
		} while (x % 2 != 0);
		pSnakeNode p = snake->_snake;
		while (p)
		{
			if (p->x == x && p->y == y)
				goto again;
			p = p->next;
		}
	food->x = x;
	food->y = y;
	snake->_food = food;
	setpos(food->x, food->y);
	wprintf(L"%c", FOOD);
}
void gameinfo(pSnake snake)
{
	setpos(70, 6);
	printf("分数:%d", snake->_score);
	setpos(70, 7);
	printf("奖励:%d", snake->_weight);
	setpos(62, 15);
	printf("游戏规则如下:\n");
	setpos(62, 16);
	printf("1.用← → ↑ ↓进行操作");
	setpos(62, 17);
	printf("2.用f1进行加速，用进行f2减速");
	setpos(62, 18);
	printf("3.空格键暂停游戏");
	setpos(62, 19);
	printf("4.esc退出游戏");
	setpos(62, 20);
	printf("5.咬到蛇身或撞墙都会死");
}
void pause()
{
	while (1)
	{
		if (Key_state(VK_SPACE))
			return;
		Sleep(1000);
	}
}
void kill_self(pSnake snake)
{
	pSnakeNode p = snake->_snake->next;
	while (p)
	{
		if (snake->_snake->x == p->x && snake->_snake->y == p->y)
		{
			snake->sta = by_self;
			return;
		}
		p = p->next;
	}
}
void snakemove(pSnake snake)
{
	pSnakeNode i = (pSnakeNode)malloc(sizeof(SnakeNode));
	assert(i);
	i->next = snake->_snake;
	if (snake->dir == up)
	{
		i->x = snake->_snake->x;
		i->y = snake->_snake->y - 1;
	}else if(snake->dir == down)
	{
		i->x = snake->_snake->x;
		i->y = snake->_snake->y + 1;
	}
	else if (snake->dir == left)
	{
		i->x = snake->_snake->x - 2;
		i->y = snake->_snake->y;
	}
	else if (snake->dir == right)
	{
		i->x = snake->_snake->x + 2;
		i->y = snake->_snake->y;
	}
	else if (snake->sta == by_end)
	{
		return;
	}
	snake->_snake = i;
	pSnakeNode p = snake->_snake;
	if (i->x==snake->_food->x&&i->y==snake->_food->y)
	{
		(snake->_score) += snake->_weight;
		setpos(70, 6);
		printf("分数:%d", snake->_score);
		setpos(70, 7);
		printf("奖励:%d", snake->_weight);
		creatfood(snake);
	}
	else
	{
		pSnakeNode pre = NULL;
		while (p->next != NULL)
		{
			pre = p;
			p = p->next;
		}
		pre->next = NULL;
		setpos(p->x, p->y);
		printf("  ");
		free(p);
	}
	if (snake->_snake->x == 0 || snake->_snake->x == 56 || snake->_snake->y == 0 || snake->_snake->y == 25)
	{
		snake->sta = by_wall;
		return;
	}
	kill_self(snake);
	p = i;
	while (p)
	{
		setpos(p->x, p->y);
		wprintf(L"%c", Body);
		p = p->next;
	}
}
void gamestart(pSnake snake)
{
	assert(snake);
	welcome();
	creatmap();
	initsnake(snake);
	creatsnake(snake);
	creatfood(snake);
	gameinfo(snake);
}
void gamerun(pSnake snake)
{
	do {
		if (Key_state(VK_UP) && snake->dir != down)
		{
			snake->dir = up;
		}
		else if (Key_state(VK_DOWN) && snake->dir != up)
		{
			snake->dir = down;
		}
		else if (Key_state(VK_LEFT) && snake->dir != right)
		{
			snake->dir = left;
		}
		else if (Key_state(VK_RIGHT) && snake->dir != left)
		{
			snake->dir = right;
		}
		else if (Key_state(VK_SPACE))
		{
			pause();
		}
		else if (Key_state(VK_ESCAPE))
		{
			snake->sta = by_end;
		}
		else if (Key_state(VK_F1))
		{
			if (snake->_sleeptime >= 80)
			{
				(snake->_sleeptime) -= 20;
				(snake->_weight) += 2;
			}
			setpos(70, 7);
			printf("奖励:%d", snake->_weight);
		}
		else if (Key_state(VK_F2))
		{
			if (snake->_sleeptime <= 280)
			{
				(snake->_sleeptime) += 20;
				(snake->_weight) -= 2;
			}
			setpos(70, 7);
			printf("奖励:%d", snake->_weight);
		}
		snakemove(snake);
		Sleep(snake->_sleeptime);
	} while (snake->sta == ok);
}
void gameend(pSnake snake)
{
	if (snake->sta==by_end)
	{
		system("cls");
		setpos(48, 15); 
		printf("游戏结束！");
		setpos(42, 22);
		system("pause");
	}
	else if (snake->sta == by_self)
	{
		system("cls");
		setpos(44, 15);
		printf("咬到自己了，游戏结束！");
		setpos(42, 22);
		system("pause");
	}
	else if (snake->sta == by_wall)
	{
		system("cls");
		setpos(44, 15);
		printf("撞到墙了，游戏结束！");
		setpos(42, 22);
		system("pause");
	}
	free(snake->_food);
	pSnakeNode p = snake->_snake;
	pSnakeNode pre = NULL;
	while (p)
	{
		pre = p;
		p = p->next;
		pre->next = NULL;
		free(pre);
	}
	free(snake);
}